﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace DbStreamConverter
{
    public class BulkCopyDataReader<TEntity> : IDataReader
    {
        private readonly IEnumerator<TEntity> _entities;

        List<Func<object, object>> getters;
        Dictionary<string, int> names;
        List<Type> types;

        public BulkCopyDataReader(IEnumerable<TEntity> entities, List<string> propList)
        {
            _entities = entities.GetEnumerator();
            var props = typeof(TEntity).GetProperties().Where(x=>propList.Contains(x.Name));
            int i = 0;
            names = props.ToDictionary(x => x.Name, x => i++);
            types = props.Select(x=>x.PropertyType.IsGenericType ? x.PropertyType.GetGenericArguments()[0] : x.PropertyType).ToList();
            getters = props.Select(x => new Func<object, object>(
                delegate(object target) { return x.GetValue(target, null); })).ToList();
        }

        public virtual bool Read() { return _entities.MoveNext(); }
        public virtual object GetValue(int i) { return getters[i](_entities.Current); }
        public virtual int FieldCount { get { return getters.Count; } }
        public virtual int GetOrdinal(string name) { return names[name]; }
        public virtual void Close() { }
        public virtual void Dispose() { }
        public virtual object this[int i] { get { throw new NotImplementedException(); } }
        public virtual int Depth { get { throw new NotImplementedException(); } }
        public virtual bool IsClosed { get { throw new NotImplementedException(); } }
        public virtual int RecordsAffected { get { throw new NotImplementedException(); } }
        public virtual DataTable GetSchemaTable() { throw new NotImplementedException(); }
        public virtual bool NextResult() { throw new NotImplementedException(); }
        public virtual object this[string name] { get { throw new NotImplementedException(); } }
        public virtual bool GetBoolean(int i) { throw new NotImplementedException(); }
        public virtual byte GetByte(int i) { throw new NotImplementedException(); }
        public virtual long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); }
        public virtual char GetChar(int i) { throw new NotImplementedException(); }
        public virtual long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); }
        public virtual IDataReader GetData(int i) { throw new NotImplementedException(); }
        public virtual string GetDataTypeName(int i) { throw new NotImplementedException(); }
        public virtual DateTime GetDateTime(int i) { throw new NotImplementedException(); }
        public virtual decimal GetDecimal(int i) { throw new NotImplementedException(); }
        public virtual double GetDouble(int i) { throw new NotImplementedException(); }
        public virtual Type GetFieldType(int i) { return types[i]; }
        public virtual float GetFloat(int i) { throw new NotImplementedException(); }
        public virtual Guid GetGuid(int i) { throw new NotImplementedException(); }
        public virtual short GetInt16(int i) { throw new NotImplementedException(); }
        public virtual int GetInt32(int i) { throw new NotImplementedException(); }
        public virtual long GetInt64(int i) { throw new NotImplementedException(); }
        public virtual string GetName(int i) { throw new NotImplementedException(); }
        public virtual string GetString(int i) { throw new NotImplementedException(); }
        public virtual int GetValues(object[] values) { throw new NotImplementedException(); }
        public virtual bool IsDBNull(int i) { throw new NotImplementedException(); }

    }

}
